package com.luo.backend.service;

import com.luo.backend.dto.*;
import com.luo.backend.entity.Food;
import com.luo.backend.entity.Merchant;
import com.luo.backend.repository.FoodRepository;
import com.luo.backend.repository.MerchantRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 搜索服务
 */
@Service
public class SearchService {
    
    private static final Logger logger = LoggerFactory.getLogger(SearchService.class);
    
    @Autowired
    private FoodRepository foodRepository;
    
    @Autowired
    private MerchantRepository merchantRepository;
    
    // 缓存商家信息，避免重复查询
    private Map<Long, Merchant> merchantCache = new HashMap<>();
    
    /**
     * 搜索商品和商家
     * 
     * @param keyword 搜索关键词
     * @param type 搜索类型：all、food、merchant
     * @param page 页码（从1开始）
     * @param pageSize 每页数量
     * @return 搜索结果
     */
    public SearchResponse search(String keyword, String type, Integer page, Integer pageSize) {
        // 清空缓存
        merchantCache.clear();
        logger.info("搜索请求 - keyword: {}, type: {}, page: {}, pageSize: {}", keyword, type, page, pageSize);
        
        SearchResponse response = new SearchResponse();
        response.setCurrentPage(page);
        response.setPageSize(pageSize);
        
        // 计算分页偏移量
        Pageable pageable = PageRequest.of(page - 1, pageSize);
        
        // 根据类型执行搜索
        if ("food".equals(type)) {
            // 只搜索商品
            searchFoodsOnly(keyword, pageable, response);
        } else if ("merchant".equals(type)) {
            // 只搜索商家
            searchMerchantsOnly(keyword, pageable, response);
        } else {
            // 搜索全部（all 或其他值）
            searchAll(keyword, pageable, response);
        }
        
        logger.info("搜索结果 - 商品数: {}, 商家数: {}", response.getTotalFoods(), response.getTotalMerchants());
        
        return response;
    }
    
    /**
     * 只搜索商品
     */
    private void searchFoodsOnly(String keyword, Pageable pageable, SearchResponse response) {
        Page<Food> foodPage = foodRepository.searchFoodsWithMerchant(keyword, pageable);
        Long totalFoods = foodRepository.countFoodsWithMerchant(keyword);
        
        response.setFoods(convertToFoodSearchDTOs(foodPage.getContent()));
        response.setMerchants(Collections.emptyList());
        response.setTotalFoods(totalFoods);
        response.setTotalMerchants(0L);
    }
    
    /**
     * 只搜索商家
     */
    private void searchMerchantsOnly(String keyword, Pageable pageable, SearchResponse response) {
        Page<Merchant> merchantPage = merchantRepository.searchMerchants(keyword, pageable);
        Long totalMerchants = merchantRepository.countMerchantsByKeyword(keyword);
        
        List<MerchantSearchDTO> merchantDTOs = convertToMerchantSearchDTOs(merchantPage.getContent());
        
        // 获取商家预览商品
        if (!merchantDTOs.isEmpty()) {
            loadPreviewFoods(merchantDTOs);
        }
        
        response.setFoods(Collections.emptyList());
        response.setMerchants(merchantDTOs);
        response.setTotalFoods(0L);
        response.setTotalMerchants(totalMerchants);
    }
    
    /**
     * 搜索全部（商品 + 商家）
     */
    private void searchAll(String keyword, Pageable pageable, SearchResponse response) {
        // 搜索商品
        Page<Food> foodPage = foodRepository.searchFoodsWithMerchant(keyword, pageable);
        Long totalFoods = foodRepository.countFoodsWithMerchant(keyword);
        
        // 搜索商家
        Page<Merchant> merchantPage = merchantRepository.searchMerchants(keyword, pageable);
        Long totalMerchants = merchantRepository.countMerchantsByKeyword(keyword);
        
        List<MerchantSearchDTO> merchantDTOs = convertToMerchantSearchDTOs(merchantPage.getContent());
        
        // 获取商家预览商品
        if (!merchantDTOs.isEmpty()) {
            loadPreviewFoods(merchantDTOs);
        }
        
        response.setFoods(convertToFoodSearchDTOs(foodPage.getContent()));
        response.setMerchants(merchantDTOs);
        response.setTotalFoods(totalFoods);
        response.setTotalMerchants(totalMerchants);
    }
    
    /**
     * 转换为商品搜索DTO列表
     */
    private List<FoodSearchDTO> convertToFoodSearchDTOs(List<Food> foods) {
        return foods.stream().map(this::convertToFoodSearchDTO).collect(Collectors.toList());
    }
    
    /**
     * 转换为商品搜索DTO
     */
    private FoodSearchDTO convertToFoodSearchDTO(Food food) {
        FoodSearchDTO dto = new FoodSearchDTO();
        dto.setId(food.getId());
        dto.setName(food.getName());
        dto.setImage(food.getImage());
        dto.setPrice(food.getPrice());
        dto.setOriginalPrice(food.getOriginalPrice());
        dto.setMerchantId(food.getMerchantId());
        dto.setSold(food.getSoldCount());
        dto.setRating(food.getRating());
        dto.setStatus(food.getStatus());
        
        // 获取商家信息
        Merchant merchant = getMerchantById(food.getMerchantId());
        if (merchant != null) {
            dto.setMerchantName(merchant.getName());
            dto.setMerchantLogo(merchant.getLogo());
        }
        
        return dto;
    }
    
    /**
     * 根据ID获取商家信息（带缓存）
     */
    private Merchant getMerchantById(Long merchantId) {
        if (merchantId == null) {
            return null;
        }
        
        // 先从缓存获取
        if (merchantCache.containsKey(merchantId)) {
            return merchantCache.get(merchantId);
        }
        
        // 从数据库查询
        Optional<Merchant> merchantOpt = merchantRepository.findById(merchantId);
        if (merchantOpt.isPresent()) {
            Merchant merchant = merchantOpt.get();
            merchantCache.put(merchantId, merchant);
            return merchant;
        }
        
        return null;
    }
    
    /**
     * 转换为商家搜索DTO列表
     */
    private List<MerchantSearchDTO> convertToMerchantSearchDTOs(List<Merchant> merchants) {
        return merchants.stream().map(this::convertToMerchantSearchDTO).collect(Collectors.toList());
    }
    
    /**
     * 转换为商家搜索DTO
     */
    private MerchantSearchDTO convertToMerchantSearchDTO(Merchant merchant) {
        MerchantSearchDTO dto = new MerchantSearchDTO();
        dto.setId(merchant.getId());
        dto.setName(merchant.getName());
        dto.setLogo(merchant.getLogo());
        dto.setRating(merchant.getRating());
        dto.setRatingCount(merchant.getRatingCount());
        dto.setMinOrderAmount(merchant.getMinOrderAmount());
        dto.setDeliveryFee(merchant.getDeliveryFee());
        dto.setStatus(merchant.getStatus());
        
        // 统计商品数量
        Long foodCount = foodRepository.countByMerchantIdAndStatus(merchant.getId(), 1);
        dto.setFoodCount(foodCount != null ? foodCount.intValue() : 0);
        
        return dto;
    }
    
    /**
     * 加载商家预览商品（每个商家最多3个）
     */
    private void loadPreviewFoods(List<MerchantSearchDTO> merchantDTOs) {
        // 提取所有商家ID
        List<Long> merchantIds = merchantDTOs.stream()
                .map(MerchantSearchDTO::getId)
                .collect(Collectors.toList());
        
        // 批量查询商家的商品
        List<Food> allFoods = foodRepository.getPreviewFoodsByMerchantIds(merchantIds);
        
        // 按商家ID分组
        Map<Long, List<Food>> foodsByMerchant = allFoods.stream()
                .collect(Collectors.groupingBy(Food::getMerchantId));
        
        // 为每个商家设置预览商品（最多3个）
        for (MerchantSearchDTO merchantDTO : merchantDTOs) {
            List<Food> merchantFoods = foodsByMerchant.getOrDefault(merchantDTO.getId(), Collections.emptyList());
            List<FoodPreviewDTO> previewFoods = merchantFoods.stream()
                    .limit(3)
                    .map(this::convertToFoodPreviewDTO)
                    .collect(Collectors.toList());
            merchantDTO.setPreviewFoods(previewFoods);
        }
    }
    
    /**
     * 转换为商品预览DTO
     */
    private FoodPreviewDTO convertToFoodPreviewDTO(Food food) {
        return new FoodPreviewDTO(food);
    }
}

